home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
PROGRAMR
/
FLAT.ZIP
/
MEMMAN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-13
|
20KB
|
652 lines
/**********************************************************************
** Program: Memory Manager
** File: memman.c
** Model: medium
** Windows: 3.x
** Version: 1.0
** Author: hb
** Date: 04/10/93
** Functions: CreateHeap creates a static heap. Only one allowed!
** DestroyHeap destroys the heap
** *AllocMemMan allocates a piece of memory in the heap
** *ReAllocMem tries to grow an allocated piece of memory
** FreeMem frees a piece of memory
** internal functions:
** GetOffset calculates the offset in the heap for a pointer
** *GetPointer calculates a pointer from a heapoffset
** GetHeapIndex returns the index of a heapnode in the heaplist
** GetFreeIndex returns the index of a freenode in the freenodelist
** GetFreeHeapIndex returns the next unused index in the heaplist
** GetFreeFreeIndex returns the next unused index in the freenodelist
** MeltFreeList tries to merge adjacent nodes in the freenodelist
** SortFreeNodes Quicksort for the freenodelist
***************************************************************************/
/* Make sure it works for ALL Windows 3.x version */
#define WIN30
/* For Borland's 'Chiseled Gray' background */
#define HAS_BWCC
/* For StratosWare MemCheck routines */
#define HAS_MEMCHECK
/******* Includes ********/
#include <windows.h>
#ifdef HAS_BWCC
#include <bwcc.h>
#endif
#define MAINMEM
#include "\borlandc\winmem\memman.h"
#ifdef HAS_MEMCHECK
#include "\wmemchec\memcheck.h"
#endif
/***CreateHeap*********************************************************
** Program: Memory Manager
** File: Memman.c
** Funktion: CreateHeap creates a heap
** - does not create a heap in realmode
** - creates only one heap because all handles stored in global vars.
** - create a freenodelist and a heapnodelist with fixed number of entries
** - heap, freenode and heapnodes are locked until destroyheap is called
** Return: error
** Author: hb
** Date: 12.6.92
****************************************************************************/
int CreateHeap (long lSize, int nMaxNodes)
{
DWORD dwInfo,
dwListSize;
long l;
/* is there already a heap? **/
if (hHeap != NULL) {
ShowMemoryError(IDE_ONLYONEHEAP);
return (IDE_ONLYONEHEAP);
}
/* get mode info **/
dwInfo = GetWinFlags();
/* calculate segment boundaries **/
if (dwInfo & WF_ENHANCED)
lSegBorder = 0L;
else if (dwInfo & WF_STANDARD)
lSegBorder = 17L;
else {
ShowMemoryError(IDE_REALMODE);
return (IDE_REALMODE);
}
/* try to allocate room for the heapnodes in global memory **/
dwListSize = sizeof (struct node);
dwListSize *= nMaxNodes;
hHeapNodes = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwListSize);
if (hHeapNodes == NULL) {
ShowMemoryError(IDE_NOMEMAVAIL);
return (IDE_NOMEMAVAIL);
}
/* try to allocate room for the freenodes in global memory **/
hFreeNodes = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwListSize);
if (hFreeNodes == NULL)
{
GlobalFree (hHeapNodes);
hHeapNodes = NULL;
ShowMemoryError(IDE_NOMEMAVAIL);
return (IDE_NOMEMAVAIL);
}
/* try to allocate room for the heap in global memory **/
hHeap = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, lSize);
if (hHeap == NULL)
{
GlobalFree (hHeapNodes);
GlobalFree (hFreeNodes);
hHeapNodes = NULL;
hFreeNodes = NULL;
ShowMemoryError(IDE_NOMEMAVAIL);
return (IDE_NOMEMAVAIL);
}
/* lock all handles to get basepointers */
HeapNodes = (LPNODE) GlobalLock (hHeapNodes);
FreeNodes = (LPNODE) GlobalLock (hFreeNodes);
if (HeapNodes == NULL || FreeNodes == NULL)
{
GlobalUnlock (hHeapNodes);
GlobalUnlock (hFreeNodes);
GlobalFree (hHeapNodes);
GlobalFree (hFreeNodes);
hHeapNodes = NULL;
hFreeNodes = NULL;
ShowMemoryError(IDE_MEMERROR);
return (IDE_MEMERROR);
}
/* calculate real size of heap **/
lHeapSize = GlobalSize (hHeap);
hpBase = (char huge *) GlobalLock (hHeap);
if (hpBase == NULL)
{
GlobalFree (hHeap);
hHeap = NULL;
ShowMemoryError(IDE_MEMERROR);
return (IDE_MEMERROR);
}
/* create the startup entries in freenodes, one entry per segment **/
for (l=0L,nFreeUsed=0;l<lHeapSize;nFreeUsed++,l+=SEGMENT)
{
FreeNodes[nFreeUsed].lOffset = (long) nFreeUsed * SEGMENT;
if ((lHeapSize - l) / SEGMENT > 0L)
FreeNodes[nFreeUsed].lSize = SEGMENT - lSegBorder;
else
FreeNodes[nFreeUsed].lSize = lHeapSize - ((long) nFreeUsed * SEGMENT);
}
nHeapUsed = 0;
nNodes = nMaxNodes;
return (IDE_OK);
}
/***DestroyHeap********************************************************
** Program: Memory Manager
** File: Memman.c
** Funktion: DestroyHeap destroys the heap
** Return: error
** Author: hb
** Date: 12.6.92
****************************************************************************/
int DestroyHeap (void)
{
/* is ther a heap ? **/
if (hHeap == NULL)
return (IDE_NOHEAP);
/* free nodelists and heap */
GlobalUnlock (hHeapNodes);
GlobalUnlock (hFreeNodes);
GlobalFree (hHeapNodes);
GlobalFree (hFreeNodes);
hHeapNodes = NULL;
hFreeNodes = NULL;
GlobalUnlock (hHeap);
GlobalFree (hHeap);
hHeap = NULL;
hpBase = NULL;
nFreeUsed = 0;
nHeapUsed = 0;
nNodes = 0;
return (IDE_OK);
}
/***AllocMemMan***********************************************************
** Program: Memory Manager
** File: Memman.c
** Funktion: AllocMemMan dynamically gets a piece of memory from the heap
** and returns a FAR pointer to it
** Return: Pointer to object, NULL if error
** Author: hb
** Date: 12.6.92
****************************************************************************/
void far *AllocMemMan (long lSize)
{
int i,
nIndex,
nError;
void far *lpReturn;
/* Init **/
lpReturn = NULL;
/* if size == 0 return error **/
if (lSize == 0L)
return (lpReturn);
/* do we have a free heapnode ? **/
nIndex = GetFreeHeapIndex ();
/* search for block large enough for the request **/
for (i=0;nIndex != nNodes && i<nFreeUsed;i++)
{
if (FreeNodes[i].lSize >= lSize)
{
lpReturn = GetPointer (FreeNodes[i].lOffset);
/******* create entry in heapnodes **/
HeapNodes[nIndex].lSize = lSize;
HeapNodes[nIndex].lOffset = FreeNodes[i].lOffset;
/******* split node in freenodes **/
FreeNodes[i].lSize -= lSize;
FreeNodes[i].lOffset += lSize;
if (FreeNodes[i].lSize == 0L)
FreeNodes[i].lOffset = 0L;
break;
}
}
/* no room for the request, try to reorganize heap to satisfy the request **/
if (lpReturn == NULL)
{
nError = MeltFreeList ();
/**** try again **/
for (i=0;nError == IDE_OK && nIndex != nNodes && i<nFreeUsed;i++)
{
if (FreeNodes[i].lSize >= lSize)
{
lpReturn = GetPointer (FreeNodes[i].lOffset);
HeapNodes[nIndex].lSize = lSize;
HeapNodes[nIndex].lOffset = FreeNodes[i].lOffset;
FreeNodes[i].lSize -= lSize;
FreeNodes[i].lOffset += lSize;
if (FreeNodes[i].lSize == 0L)
FreeNodes[i].lOffset = 0L;
break;
}
}
}
return (lpReturn);
}
/***ReAllocMem***********************************************************
** Program: Memory Manager
** File: Memman.c
** Funktion: ReAllocMem changes size of allocated previously allocated objct
** - if size == 0, free node
** - if there is no adjacent node to satisfy request, move block to